package com.hanxiaozhang.delayqueue.no1;

import lombok.Data;

import java.util.Date;
import java.util.concurrent.Delayed;
import java.util.concurrent.TimeUnit;

/**
 * 〈一句话功能简述〉<br>
 * 〈实现Delayed接口〉
 * <p>
 * Delayed接口实现了Comparable接口，提供了long getDelay(TimeUnit unit)，返回一个数字，
 * 这个数字表示这个对象剩余的时间，数字为0或者负数意味着这个对象已经到期。
 * <p>
 * 如果一个对象实现了这个接口，就必须要实现两个方法：getDelay()、compareTo()
 *
 * @author hanxinghua
 * @create 2022/9/11
 * @since 1.0.0
 */
@Data
public class ItemDelayed<T> implements Delayed {

    /**
     * 默认延迟30分钟*
     */
    private final static long DELAY = 30 * 60 * 1000L;

    /**
     * 数据id
     */
    private Long dataId;

    /**
     * 开始时间
     */
    private long startTime;

    /**
     * 到期时间
     */
    private long expire;

    /**
     * 创建时间
     */
    private Date now;

    /**
     * 泛型data
     * Tips:尽量不要添加，队列中数据过多时，会很吃内存
     */
    private T data;

    public ItemDelayed(Long dataId, long startTime, long secondsDelay) {
        super();
        this.dataId = dataId;
        this.startTime = startTime;
        this.expire = startTime + (secondsDelay * 1000);
        this.now = new Date();
    }

    public ItemDelayed(Long dataId, long startTime) {
        super();
        this.dataId = dataId;
        this.startTime = startTime;
        this.expire = startTime + DELAY;
        this.now = new Date();
    }

    @Override
    public int compareTo(Delayed o) {
        return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));
    }


    /**
     * 通过给定的实际单位，返回剩余有效期。
     * Tips：
     * 如果返回的是负数则说明到期否则还没到期
     *
     * @param unit the time unit
     * @return
     */
    @Override
    public long getDelay(TimeUnit unit) {
        return unit.convert(this.expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
    }
}
